package com.minelx.sequence.core;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import static java.util.stream.Collectors.toList;

public class ThenMatcher<R> implements ReturnMatcher<List<R>, StringScanner> {
	private final List<ReturnMatcher<? extends R, StringScanner>> matchers;

	private ThenMatcher(List<ReturnMatcher<? extends R, StringScanner>> matchers) {
		this.matchers = matchers;
	}

	public void then(ReturnMatcher<? extends R, StringScanner> matcher) {
		matchers.add(matcher);
	}

	@Override
	public boolean isMatch(StringScanner clue) {
		StringScanner copied = clue.copy();
		return matchers.stream().allMatch(matcher -> matcher.match(copied));
	}

	@Override
	public List<R> onMatched(StringScanner clue) {
		return matchers.stream()
				.map(matcher -> matcher.get(clue)
						.orElseThrow(() -> new IllegalArgumentException("clue not satisfy the matcher: " + matcher)))
				.collect(toList());
	}

	@SafeVarargs
	public static <R> ThenMatcher<R> of(ReturnMatcher<R, StringScanner>... matchers) {
		return new ThenMatcher<>(Arrays.asList(matchers));
	}

	public static <R> ThenMatcher<R> of(List<ReturnMatcher<? extends R, StringScanner>> matchers) {
		return new ThenMatcher<>(matchers);
	}

	public static <R> ThenMatcher<R> empty() {
		return new ThenMatcher<>(new LinkedList<>());
	}
}
